<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
</head>

<body>
  <div id="app">
    <h4>.sync</h4>
    <h4>插槽</h4>
    <box v-slot="slotProps">{{slotProps.val}}</box>
    <!-- 解构的样式 -->
    <box v-slot="{val}">{{val}}</box>
    <h4>组件化</h4>
    <p>input封装成组建使用v-model</p>
    <custom-input v-model="inputValue"></custom-input>
    <p>{{inputValue}}</p>
    <div :style="{fontSize: postFontSize + 'em'}">
      <blog-post v-for="item in posts" :key="item.id" :post="item" @enlarge-text="onEnlargeText"></blog-post>
    </div>
    <template>
      <my-button></my-button>
      <my-button></my-button>
      <my-button></my-button>
    </template>
    <br />
    表单绑定用法
    <input v-model.lazy="inputValue" />
    {{inputValue}}
    <br />
    <textarea v-model="textArea"></textarea>
    {{textArea}}
    <br />
    <input type="checkbox" v-model="checked" />
    <label>单个复选框{{checked}}</label>
    <br />
    多个复选框
    <input type="checkbox" id="jack" value="j1" v-model="checkList" />
    <label for="jack">Jack</label>
    <input type="checkbox" id="john" value="John" v-model="checkList" />
    <label for="john">John</label>
    <input type="checkbox" id="mike" value="Mike" v-model="checkList" />
    <label for="mike">Mike</label>
    <br />
    <span>Checked names: {{ checkList }}</span>
    <br />
    <input type="radio" value="1" id="1" v-model="choosen" />
    <label for="1">1</label>
    <input type="radio" value="2" id="2" v-model="choosen" />
    <label for="2">2</label>
    <br />
    <span>radio: {{choosen}}</span>
    <br />
    <select v-model="selected">
      <option v-for="item in options" :value="item.value">
        {{item.text}}
      </option>
    </select>
    you selected {{selected}}
    <br />
    <button @click="say('hh', $event)">saysome</button>
    元素上使用 v-if 条件渲染分组
    <template v-if="seen">
      <p>can you seen me??</p>
      <p>can you seen me,too??</p>
    </template>
    <button :disabled="isDisabled">this is a button</button>
    <todo-item v-for="i in list" :todo="i" :key="i.id"></todo-item>
    is属性
    <ul>
      <li is="todo-item" v-for="i in list" :key="i.id" :todo="i"></li>
    </ul>
    遍历object
    <!-- <li v-for="(val, n) in object">{{n}}: {{val}}</li> -->
    <!-- <todo-item/>   -->
    {{message}} 计算属性：{{reverseMessage1}}
    <p v-once>一个不会变的值 {{message}}</p>
    <div>
      <p v-if="seen">see me</p>
      <span :title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息！</span>
    </div>
    <!-- <div v-for="item in list" :key="item.id">
      {{item.text}}
    </div> -->
    <!-- <div v-on:click="reverseMsg"> -->
    <!-- 动态参数 :[app.value] -->
    <div @[event]="reverseMsg">消息反转</div>
    <p>form双向绑定</p>
    <input v-model="msg" />
    <h4>.sync</h4>
    <doc :t.sync="object.title"></doc>
    <h4>具名插槽</h4>
    <base-layout>
      <!-- <template v-slot:header>
            this is a header
          </template> -->
      <!-- 具名插槽的缩写 -->
      <template #header>this is a header</template>
      <template v-slot:default>this is a main content</template>
      <template v-slot:footer>this is a footer</template>
    </base-layout>
    <p>自定义指令</p>
    <input v-focus v-demo:my-arg.sync="{id:1, text:'hello'}">
    <p>nextTick</p>
    <button @click="onChange">count: {{count}}</button>
    <p>keep-alive切换组件时进行缓存</p>
    <button @click="changeView">changeView</button>
    <keep-alive>
      <component :is="currentView" :[keepaliveparams].sync="object.title"></component>
    </keep-alive>
    
  </div>
  <div id="mount-point"></div>

  <!-- 引入vue2 -->
  <script src="vue.js"></script>
  <script>
    //Vue.nextTick dom更新之后的回调 返回的是promise对象
    Vue.nextTick()
      .then(function () {
        console.log('nextTick')
      })
    //Vue.extend
    var Profile = Vue.extend({
      data() {
        return {
          firstName: 'Foo',
          lastName: 'Bar',
          bio: 'Lorem ipsum...'
        }
      },
      created() {
        console.log('profile vm created')
      }
    })
    var profile = new Profile();
    //自定义指令
    //directive 全局注册
    // Vue.directive('focus', {
    //   inserted (el) {
    //     el.focus()
    //   }
    // })
    /**
     * 混入
     * */
    // 定义一个混入对象

    var myMixin = {
      created() {
        this.hello()
      },
      data() {
        return {
          a: 'a',
          b: 'b',
        }
      },
      methods: {
        hello() {
          console.log("混入+继承 hello from mixin!")
        },
        foo: function () {
          console.log('foo')
        },
        conflicting: function () {
          console.log('from mixin')
        }
      },
    }
    var extendObj = {
      data() {
        return {
          c: 'c',
          d: 'd',
        }
      },
      created() {
        console.log('混入+继承 extend test')
      },
      methods: {
        conflicting: function () {
          console.log('from extendobj')
        }
      },
    }
    // 定义一个使用混入对象的组件
    var Component = Vue.extend({
      mixins: [myMixin],
      
    })

    // var component = new Component()

    /**
     * 创建组件的方法
     * !props相当于一个组件的属性列表，接受父级的值，标签需要用v-bind绑定父级的值
     * ! 计算属性相当于 将data进行复杂逻辑之后的data
     * */
    Vue.component("base-layout", {
      // 混入-选项合并-参数：合并混入元素的变量，重名元素以父级为准
      // 混入-选项合并-钩子：同名的，混入的先调用
      // 多继承
      mixins: [myMixin],
      extends: extendObj,//单继承
      created() {
        console.log('混入+继承', this.$data, this.conflicting())
      },
      methods: {
        conflicting: function () {
          console.log('from base-layout-component')
        }
      },
      data() {
        return {
          b: 'cc'
        }
      },
      template: `
             <div class="container">
                <header>
                  <slot name="header">hh</slot>
                </header>
                <main>
                  <slot></slot>
                </main>
                <footer>
                    <slot name="footer"></slot>
                </footer>
             </div>
            `,
    })
    Vue.component("doc", {
      props: ["t"],
      template: `
              <div>
                  <p>{{t}}</p>
                  <button @click="$emit('update:t','haha')">change</button>
              </div>
            `,
      created () {
        console.log('doc created')
        console.log('my parent is ',this.$parent)
      },
      activated () {
        console.log('doc activated')
      },
      deactivated () {
        console.log('doc deactivated')
      },
    })
    Vue.component("box", {
      created () {
        console.log('box created')
      },
      activated () {
        console.log('box activated')
      },
      deactivated () {
        console.log('box deactivated')
      },
      
      data() {
        return {
          val: "a val",
        }
      },
      template: `
              <div>
                {{this.foo}}
                {{val}}
                <span>a box</span>
                <slot :val="val">defalut</slot>
              </div>
            `,
    })
   
     
    var myButton = {
      data() {
        return {
          count: 0,
        }
      },
      template: `<button @click="count++">count:{{count}}</button>`,
    }
    var customInput = {
      props: ["value"],
      template: `
              <input
                :value="value"
                @input="$emit('input', $event.target.value)"
              >
            `,
    }
    var blogPost = {
      props: ["post"],
      template: `
            <div>
              <h4>{{post.title}}</h4>
              <p v-html="post.title"></p>
              <button @click="$emit('enlarge-text', 0.1)">enlarge it</button>
            </div>
            `,
      methods: {},
      inject: ['foo'],
      created() {
        console.log('blog-post created',this.foo)
      },
    }
    var todoItem = {
      props: ["todo"],
      template: `<li>{{todo.text}}, {{this.foo}}</li>`,
    }
    var app = new Vue({
      el: "#app",
      components: {
        "my-button": myButton,
        "custom-input": customInput,
        "blog-post": blogPost,
        "todo-item": todoItem,
      },
      data: {
        message: "this is a message",
        msg: "用来双向绑定的",
        seen: true,
        count: 0,
        list: [
          { id: 0, text: "hello" },
          { id: 1, text: "haha" },
          { id: 3, text: "rose" },
        ],
        isDisabled: false,
        event: "click",
        // event: null
        // isDisabled: null
        object: {
          title: "How to do lists in Vue",
          author: "Jane Doe",
          publishedAt: "2016-04-10",
        },
        // 表单数据
        inputValue: "",
        textArea: "",
        checked: false,
        checkList: [],
        choosen: "",
        selected: "A",
        options: [
          { text: "One", value: "A" },
          { text: "Two", value: "B" },
          { text: "Three", value: "C" },
        ],
        posts: [
          { id: 11, title: "My journey with Vue" },
          { id: 22, title: "Blogging with Vue" },
          { id: 33, title: "Why Vue is so fun" },
        ],
        postFontSize: 1,
        dynamicSlotName: "header",
        currentView: 'doc',
        keepaliveparams :'t',
        isChange: false
      },
      // 计算属性
      computed: {
        reverseMessage() {
          this.fnFromCreate()
          return this.message.split("").reverse().join("")
        },
        reverseMessage1: {
          get() {
            return this.message.split("").reverse().join("")
          },
          set(val) {
            this.message = val
          },
        },
      },
      //监听属性
      watch: {
        message() {
          this.fnFromCreate()
        },
      },
      provide: {
        foo: "【provide/inject】this is a message from provide",
      },
      methods: {
        reverseMsg() {
          // console.log(this)
          this.message = [...this.message].reverse().join("")
        },
        fn() {
          return "just a function"
        },
        say(msg, event) {
          alert("say: " + msg + "--" + event.target)
        },
        onEnlargeText(val) {
          this.postFontSize += val
        },
        onChange() {
          this.count++
          console.log('count', this.count)
          this.$nextTick(() => {
            console.log('nextTick count', this.count)

          })
        },
        changeView() {
          this.isChange =!this.isChange
          this.currentView = this.isChange? 'doc' : 'box'
        },
      },
      // 自定义指令-局部注册
      directives: {
        demo: {
          bind(el, binding, vnode) {
            console.log('directive--bind--demo')
            console.log(el)
            console.log(binding)
            console.log(vnode)
          },
          inserted(el, binding, vnode) {
            console.log('directive--inserted--demo')
            console.log(el)
            console.log(binding)
            console.log(vnode)
          }
        },
        focus: {
          //被绑定元素插入父节点时调用
          inserted(el) {
            console.log('directive--inserted')
            el.focus()
          },
          //只调用一次，指令第一次绑定到元素时调用
          bind() {
            console.log('directive--bind')
          },
          //指令与元素解绑时调用
          unbind() {
            console.log('directive--unbind')
          },
          //指令所在组件的 VNode 更新后调用
          updated() {
            console.log('directive--updated')
          }
        }
      },
      // 生命周期hooks
      beforeCreate: function () {
        console.log("vm breforeCreate")
      },
      created: function () {
        // 实例创建完成，可以调用实例上的属性和方法
        this.fnFromCreate = function () {
          console.log("i am a " + this.fn() + "from create")
        }
        console.log("vm created!", this.message)
        
        // this.$nextTick(() => {
        //   console.log('nextTick my child is ',this.$children)
        //   this.$children.forEach((item) => {
        //     console.log(item.name)
        //   })
        // })
      },
      beforeMount: function () {
        console.log("vm beforeMount")
      },
      mounted: function () {
        //可以访问dom
        console.log("vm mounted")
      },
      beforeUpdate: function () {
        console.log("vm beforeUpdate", this.message)
      },
      updated: function () {
        console.log("vm updated", this.message)
      },
      beforeDestroy: function () {
        console.log("vm beforeDestroy")
      },
      destroyed: function () {
        console.log("vm destroyed")
      },
    })
  </script>
</body>

</html>